﻿#include "Log4cplus.h"
#include "log4cplus/fileappender.h"
#include "log4cplus/win32debugappender.h"
#include "log4cplus/Win32ConsoleAppender.h"
#include "log4cplus/consoleappender.h"

BEGIN_NAMESPACE_CIQTEK

#define MAX_PATH_LEN 256

#ifdef WIN32
#ifdef UNICODE
#define ACCESS(fileName,accessMode) _waccess(fileName,accessMode)
#define MKDIR(path) _wmkdir(path)
#else
#define ACCESS(fileName,accessMode) _access(fileName,accessMode)
#define MKDIR(path) _mkdir(path)
#endif // UNICODE
#else
#define ACCESS(fileName,accessMode) access(fileName,accessMode)
#define MKDIR(path) mkdir(path,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)
#endif // WIN32

int32_t MyCreateDirectory(const tstring &directoryPath)
{
    uint32_t dirPathLen = directoryPath.size();
    if (dirPathLen > MAX_PATH_LEN)
    {
        return -1;
    }
    tchar tmpDirPath[MAX_PATH_LEN] = { 0 };
    for (uint32_t i = 0; i < dirPathLen; ++i)
    {
        tmpDirPath[i] = directoryPath[i];
        if (tmpDirPath[i] == '\\' || tmpDirPath[i] == '/')
        {
            if (ACCESS(tmpDirPath, 0) != 0)
            {
                int32_t ret = MKDIR(tmpDirPath);
                if (ret != 0)
                {
                    return ret;
                }
            }
        }
    }
    return 0;
}

Log4cplus::Log4cplus()
    : m_isShowLogger(false)
{
    
}

Log4cplus::~Log4cplus()
{

}

Log4cplus & Log4cplus::getInstance()
{
    static Log4cplus logImpl;
    return logImpl;
}

void Log4cplus::init(const QString logPath, LogLevel level, bool isShowLogger)
{
    log4cplus::initialize();
    LogHelper::getInstance().installMessageHandler(Log4cplus::printLog);

    m_strLogPath = logPath;
    m_logLevel = level;
    m_isShowLogger = isShowLogger;

    // 创建目录
    MyCreateDirectory(m_strLogPath.toStdWString().c_str());

    // 获取RootLogger并设置，子Logger自动继承
    log4cplus::Logger logger = log4cplus::Logger::getRoot();
    logger.setLogLevel(m_logLevel);

#ifdef _DEBUG
    // 调试版全部输出到控制台
    logger.addAppender(GetDebugAppender());
#else
    logger.addAppender(GetFileAppender());
#endif
}

void Log4cplus::release()
{
    log4cplus::deinitialize();
}

void Log4cplus::printLog(LogLevel ll, QString log)
{
    //assert(!log.isEmpty());

    // 根据日志类型输出日志
    switch (ll)
    {
    case LOG_LEVEL_TRACE:
        trace(log);
        break;
    case LOG_LEVEL_DEBUG:
        debug(log);
        break;
    case LOG_LEVEL_INFO:
        info(log);
        break;
    case LOG_LEVEL_WARN:
        warn(log);
        break;
    case LOG_LEVEL_ERROR:
        error(log);
        break;
    case LOG_LEVEL_FATAL:
        fatal(log);
        break;
    default:
        break;
    }
}

void Log4cplus::trace(QString log)
{
    LOG4CPLUS_TRACE(log4cplus::Logger::getRoot(), log.toStdWString().c_str());
}

void Log4cplus::debug(QString log)
{
    LOG4CPLUS_TRACE(log4cplus::Logger::getRoot(), log.toStdWString().c_str());
}

void Log4cplus::info(QString log)
{
    LOG4CPLUS_TRACE(log4cplus::Logger::getRoot(), log.toStdWString().c_str());
}

void Log4cplus::warn(QString log)
{
    LOG4CPLUS_WARN(log4cplus::Logger::getRoot(), log.toStdWString().c_str());
}

void Log4cplus::error(QString log)
{
    LOG4CPLUS_ERROR(log4cplus::Logger::getRoot(), log.toStdWString().c_str());
}

void Log4cplus::fatal(QString log)
{
    LOG4CPLUS_FATAL(log4cplus::Logger::getRoot(), log.toStdWString().c_str());
}

SharedAppenderPtr Log4cplus::GetFileAppender()
{
    SharedAppenderPtr fileAppender(new RollingFileAppender(m_strLogPath.toStdWString().c_str(), 200 * 1024 * 1024, 5));
    log4cplus::tstring strPattern;
    if (m_isShowLogger)
    {
        strPattern = LOG4CPLUS_C_STR_TO_TSTRING("[%D{%y-%m-%d %H:%M:%S,%q}] [%-5t] [%-5p] [%c{2}] - %m %n");
    }
    else
    {
        strPattern = LOG4CPLUS_C_STR_TO_TSTRING("[%D{%y-%m-%d %H:%M:%S,%q}] [%-5t] [%-5p] - %m %n");
    }
    PatternLayout* pFileLayout = new PatternLayout(strPattern);
    fileAppender->setLayout(std::unique_ptr<PatternLayout>(pFileLayout));
    fileAppender->setName(LOG4CPLUS_TEXT("fileAppender"));
    return fileAppender;
}

SharedAppenderPtr Log4cplus::GetDebugAppender()
{
    SharedAppenderPtr consoleAppender(new Win32DebugAppender);
    //SharedAppenderPtr consoleAppender(new Win32ConsoleAppender);
    log4cplus::tstring strPattern;
    if (m_isShowLogger)
    {
        strPattern = LOG4CPLUS_C_STR_TO_TSTRING("[%D{%H:%M:%S,%q}] [%-5t] [%-5p] [%c{2}] - %m %n");
    }
    else
    {
        strPattern = LOG4CPLUS_C_STR_TO_TSTRING("[%D{%H:%M:%S,%q}] [%-5t] [%-5p] - %m %n");
    }
    PatternLayout* pConsoleLayout = new PatternLayout(strPattern);
    consoleAppender->setLayout(std::unique_ptr<PatternLayout>(pConsoleLayout));
    consoleAppender->setName(LOG4CPLUS_TEXT("consoleAppender"));
    return consoleAppender;
}

END_NAMESPACE_CIQTEK